//AvenirMQ用户管理模块
const fs = require('fs');
const libcu = require('libcu');
const { toLog, SUCCESS, delQuotation, getSign, AvenirMQ_ALL } = require('../common/common');
class User {
    constructor() {
        this.userList = {};
        this.fileName = ini.mq.userFileName;
        this.binds = {};
        this.getUserList();
        this.createBinds();
    }

    //从用户配置文件中获取用户信息
    getUserList() {
        if (!fs.existsSync(this.fileName)) {
            fs.writeFileSync(this.fileName, "{}");
            this.userList = {};
        } else {
            let users = fs.readFileSync(this.fileName);
            try {
                this.userList = JSON.parse(users);
            } catch (err) {
                this.userList = {};
                fs.writeFileSync(this.fileName, "{}");
            }
        }
    }


    //新建用户 JSON格式:
    // json = {
    //     name :'test',
    //     password:'11111111',//AES加密,
    //     ip:"127.0.0.1",
    //     port:'13000',
    //     key:'a.b.rpc',
    // }

    addUser(data) {
        if (this.userList[data.name]) {
            throw ('USER_EXISTS');
        }
        data.key = this.parseKey(data.key);
        if (data.key.to == AvenirMQ_ALL) {
            throw ("KEY_ANY_ERROR");
        }
        //把内容存起来
        let password = libcu.cipher.AesDecode(data.password);
        toLog('password = ',password);
        password = delQuotation(password);
        data.password = password;
        this.userList[data.name] = data;
        toLog(`this.userList[${data.name}] = `, this.userList[data.name]);
        this.refresh(true);

        throw (SUCCESS);
    }

    //删除用户 删除用户不需要验证密码
    delUser(data) {
        if (!this.userList[data.name]) {
            throw ('USER_NOW_FOUND');
        }
        delete this.userList[data.name];
        this.refresh(true);

        throw (SUCCESS);
    }

    //修改用户信息
    updateUser(data) {
        if (!this.userList[data.name]) {
            throw ('USER_NOW_FOUND');
        }
        data.key = this.parseKey(data.key);
        //把内容存起来
        let password = libcu.cipher.AesDecode(data.password);
        password = delQuotation(password);
        data.password = password;
        this.userList[data.name] = data;
        toLog(`this.userList[${data.name}] = `, this.userList[data.name]);
        this.refresh(true);
        throw (SUCCESS);
    }

    //用户登录 判断登录是否合法
    async login(data) {
        if (!data.name || !data.password) {
            throw ('INVALID_LOGIN');
        }
        let password = delQuotation(libcu.cipher.AesDecode(data.password));
        toLog("password = ", password);
        if (!this.userList[data.name] || this.userList[data.name].password != password) {
            throw ('INVALID_LOGIN');
        }
        //其他的就成功了
        let sign = getSign(data.name, data.password);
        toLog("生成签名", sign);
        return sign;
    }

    //解析绑定时的from.to.key
    parseKey(keys) {
        let arr = keys.split('.');
        if (arr.length != 3) {
            throw ("BAD_KEYS");
        }
        return {
            send: arr[0],
            to: arr[1],
            type: arr[2],
        }
    }

    //展示所有用户信息
    showUserLists() {
        let arr = [];
        for (let key in this.userList) {
            arr.push(this.userList[key].name);
        }
        throw ({ code: SUCCESS, data: arr });
    }

    //查用户信息 需要验签
    queryUser(data, ifAll) {

    }

    //创建绑定信息
    createBinds(redo) {
        !redo || (this.binds = {});
        for (let sign in this.userList) {
            let key = this.userList[sign].key;
            //如果没有待发送的信息  就创建
            if (!this.binds[key.send]) {
                this.binds[key.send] = [];
            }
            // 20210121 注意这里应该是绑定send而不是to，不然消息会短路 自己发给自己了
            let res = {
                type: key.type,
                sign,
                ip: this.userList[sign].ip,
                port: this.userList[sign].port,
                //增加接收方名称信息
                receive: this.userList[sign].key.send,
            };
            this.binds[key.send].push(res);
        }
        toLog("this.binds = ", JSON.stringify(this.binds));
    }

    refresh(redo) {
        fs.writeFileSync(this.fileName, JSON.stringify(this.userList, null, 4));
        this.createBinds(redo);
    }
}

module.exports = User;